package service

import (
	"advertising/config/mysql"
	"advertising/internal/dao"
	"advertising/internal/define"
	"advertising/internal/models"
	"context"
	"regexp"
	"sort"
	"strings"
	"time"

	"github.com/samber/lo"
)

type MaterialFolder struct{}

const (
	TopGroupID       = "-1"
	DefaultGroupID   = "0"
	DefaultGroupName = "默认文件夹"
	MaxGroupCount    = 10
)

// FolderSave 文件夹新增编辑
func (MaterialFolder) FolderSave(ctx context.Context, merchantID, ID, PID string, Type int8, name string) (err error) {
	db := mysql.NewDB()
	if ID == DefaultGroupID {
		return define.ErrDefaultGroupShouldNotUpdate
	}
	if Type != 1 && Type != 2 {
		return define.ErrGroupTypeInvalid
	}

	if strings.TrimSpace(name) == "" {
		return define.ErrGroupNameRequired
	}
	regRes, _ := regexp.MatchString(define.GroupNameRegular, strings.TrimSpace(name))
	if !regRes {
		return define.ErrGroupNameRegularNotMatch
	}
	if name == DefaultGroupName {
		return define.ErrGroupNameExist
	}
	if PID == "" {
		return define.ErrParentGroupRequire
	}
	if PID != TopGroupID {
		// 判断父文件夹是否存在
		PIDInfo, _ := dao.MaterialFolder{}.Detail(ctx, db, merchantID, PID, Type)
		if PIDInfo.ID == "" {
			return define.ErrParentGroupNoExist
		}
		if PIDInfo.PID != TopGroupID {
			return define.ErrChildrenGroupShouldNotHaveChild
		}
	}

	// 同父级的子文件夹数量
	_, PIDChildrenCount, _ := dao.MaterialFolder{}.List(ctx, db, merchantID, nil, PID, Type)
	if ID == "" {
		// 最多10个文件夹
		if PIDChildrenCount >= MaxGroupCount {
			return define.ErrGroupMaxCount
		}
		// 文件夹名称已被占用
		nameExist, err := dao.MaterialFolder{}.SameNameExist(ctx, db, merchantID, name, Type, ID)
		if err != nil {
			return err
		}
		if nameExist {
			return define.ErrGroupNameExist
		}
		// 写入数据库
		dao.MaterialFolder{}.Create(ctx, db, merchantID, name, Type, PID)
	} else {
		// 最多10个文件夹
		if PIDChildrenCount > MaxGroupCount {
			return define.ErrGroupMaxCount
		}
		// 文件夹名称已被占用
		nameExist, err1 := dao.MaterialFolder{}.SameNameExist(ctx, db, merchantID, name, Type, ID)
		if err1 != nil {
			return err1
		}
		if nameExist {
			return define.ErrGroupNameExist
		}
		// 文件夹是否存在
		folderInfo, _ := dao.MaterialFolder{}.Detail(ctx, db, merchantID, ID, Type)
		if folderInfo.ID == "" {
			return define.ErrGroupNoExist
		}
		// 更新数据库
		dao.MaterialFolder{}.Update(ctx, db, merchantID, ID, name, 0, PID, nil)
	}
	return
}

type FolderList struct {
	models.MaterialFolder
	Children []FolderList `json:"children"`
}

// FolderList 文件夹列表
func (MaterialFolder) FolderList(ctx context.Context, merchantID string, Type int8) (data []FolderList, err error) {
	db := mysql.NewDB()
	if Type != 1 && Type != 2 {
		return data, define.ErrGroupTypeInvalid
	}
	defaultGroup := FolderList{
		MaterialFolder: models.MaterialFolder{
			ID:         DefaultGroupID,
			MerchantID: merchantID,
			Name:       DefaultGroupName,
			Type:       Type,
			PID:        TopGroupID,
			CreatedAt:  time.Now().Unix(),
		},
		Children: []FolderList{},
	}
	var GroupMap = make(map[string][]FolderList)
	List, _, _ := dao.MaterialFolder{}.List(ctx, db, merchantID, nil, "", Type)
	for _, v := range List {
		item := FolderList{
			MaterialFolder: *v,
			Children:       []FolderList{},
		}
		GroupMap[v.PID] = append(GroupMap[v.PID], item)
	}

	var Res = []FolderList{}
	for _, v := range List {
		sort.Slice(GroupMap[v.ID], func(i int, j int) bool {
			return GroupMap[v.ID][i].Sort < GroupMap[v.ID][j].Sort
		})
		if GroupMap[v.ID] == nil {
			GroupMap[v.ID] = []FolderList{}
		}
		if v.PID == TopGroupID {
			Res = append(Res, FolderList{
				MaterialFolder: *v,
				Children:       GroupMap[v.ID],
			})
		}
	}
	sort.Slice(Res, func(i int, j int) bool {
		return Res[i].Sort < Res[j].Sort
	})
	return append([]FolderList{defaultGroup}, Res...), nil
}

// FolderDelete 文件夹删除
func (MaterialFolder) FolderDelete(ctx context.Context, merchantID, ID string) (err error) {
	db := mysql.NewDB()
	if ID == "" {
		return define.ErrGroupIDRequire
	}
	if ID == DefaultGroupID {
		return define.ErrDefaultGroupShouldNotDelete
	}

	// 查询是否存在
	folderInfo, _ := dao.MaterialFolder{}.Detail(ctx, db, merchantID, ID, 0)
	if folderInfo.ID == "" {
		return define.ErrGroupNoExist
	}
	// 文件夹有素材时不允许删除
	_, materialCount := dao.Material{}.Detail(ctx, db, merchantID, "", ID, 0)
	if materialCount != 0 {
		return define.ErrGroupInUse
	}
	// 子文件夹有素材时不允许删除
	if folderInfo.PID == TopGroupID {
		var childrenList []string
		list, _, _ := dao.MaterialFolder{}.List(ctx, db, merchantID, nil, ID, 0)
		for _, v := range list {
			childrenList = append(childrenList, v.ID)
		}
		if len(childrenList) > 0 {
			_, materialCount := dao.Material{}.Detail(ctx, db, merchantID, "", strings.Join(childrenList, ","), 0)
			if materialCount != 0 {
				return define.ErrChildGroupInUse
			}
		}
	}
	// 删除文件夹
	dao.MaterialFolder{}.Delete(ctx, db, merchantID, ID, "")
	// 删除子文件夹
	dao.MaterialFolder{}.Delete(ctx, db, merchantID, "", ID)
	return nil
}

// FolderSort 文件夹排序
func (MaterialFolder) FolderSort(ctx context.Context, merchantID string, sort []struct {
	ID   string `json:"id"`
	Sort int8   `json:"sort"`
}) (err error) {
	db := mysql.NewDB()
	var GroupIDList []string
	for _, v := range sort {
		if v.ID == "" {
			return define.ErrGroupIDRequire
		}
		if v.ID == DefaultGroupID {
			return define.ErrDefaultGroupShouldNotSort
		}
		if v.Sort < 0 {
			return define.ErrGroupSortUnexpacted
		}
		if lo.Contains(GroupIDList, v.ID) {
			return define.ErrGroupIDDuplicate
		}
		GroupIDList = append(GroupIDList, v.ID)
	}
	// 判断文件夹是否存在
	GroupList, _, _ := dao.MaterialFolder{}.List(ctx, db, merchantID, GroupIDList, "", 0)
	if len(GroupIDList) != len(GroupList) {
		return define.ErrGroupNoExist
	}

	// 检查文件夹ID是否一致
	var PIDCheck string
	for _, v := range GroupList {
		if PIDCheck == "" {
			PIDCheck = v.PID
		} else if PIDCheck != v.PID {
			return define.ErrGroupsHasDiffrentPID
		}
	}
	for _, v := range sort {
		dao.MaterialFolder{}.Update(ctx, db, merchantID, v.ID, "", 0, "", &v.Sort)
	}
	return
}
